简介
Pwn2Own 2013的漏洞,发过安全团队VUPEN他们是攻击win8的ie10,利用rop和模块基址泄露实现任意代码执行
环境及工具
Windows 7
vm 12
windbg
ida
基于类函数定位的漏洞分析方法
这个poc还是比较长的,就不贴出来了,长了之后也对漏洞分析增加了不少难度(需要的下载漏洞战争的资料就好了)
在开启了hpa的情况下,崩溃信息如下:
1 | 0:005> g |
可以看到是vgx!ORG::Get里面调用了memcpy出的异常
看看崩溃前的memcpy的参数
1 | 0:005> p |
复制的大小为4,不是问题所在,先看看报错的复制的源地址1cd3b060
1 | 0:005> !heap -p -a 1cd3b060 |
可以看到这个地址已经超过了堆的空间
1 | 0:005> ? 1cd3af50 +b0 |
看看Get函数
1 | void __stdcall ORG::Get(ORG *this, void *Dst, int a3) |
源地址来自第一个参数,我们再向上COALineDashStyleArray::get_item,但是这个还是来自上层的this
再上面就不是vgx的函数了,漏洞的出发点可能不在当前的堆栈信息中
作者又给了一种分析方法,就是尝试去理解poc的代码,其实这样的理解方式很好,会让你深刻地理解到代码的作用,触发异常或者漏洞利用的点,还可以对下一次类似代码的分析的时候提供帮助,那开始吧
一开始是一些包含,声明的东西,应该类似于我们的C,C++吧
1 | <!-- Include the VML behavior --> |
接下来看看body,加载就调用createRects函数,具体见注释
1 | <body onload="createRects();"> |
createRects函数,创建了400个v:shape元素,设置上id,并添加到body
1 | var rect_array = new Array() |
最后就是crashme
1 | function crashme(){ |
接下来我们根据作者的注释COARuntimeStyle,在ida搜索一下,一开始的操作_vgRuntimeStyle和rotation
应该跟这个类相关的
那dashstyle的操作呢,我们也可以找到操作,而且那个看着基本肯定是整数溢出的-1,我们也看到了XXXArray::put_length的操作
那我们就下来跟踪一下put_length的操作,对COALineDashStyleArray::put_length下断点,用bu吧
1 | 0:005> g |
可以看到第二个参数为-1(0xffffffff)
我们一步步跟,发现这个函数并没有什么异常,但是我们可能对DeleteRange这个函数有疑虑,
下面跟进DeleteRange,它调用了MsoDeletePx
1 | void __stdcall ORG::DeleteRange(ORG *this, int a2, int a3) |
继续
1 | int __stdcall MsoDeletePx(void *Dst, int a2, int a3) |
由于上面传递的是(char *)this + 4
,实际上当前Dst指向的就是dashstyle的长度
1 | int __stdcall MsoFRemovePx(void *Dst, int length, int a3) |
为什么是0xfffff呢,因为汇编指令是word啊
1 | sub word ptr [esi],bx |
我们看看实际内存
1 | 0:005> dd esi l1 |
实际我们只有0x2c大小,但是这里实际设置成了0xffff
所以我们后面用dashstyle.array.item索引的时候就绕过了长度检测,最终触发异常
但是这里值得思考的是,为什么要触发两个整数溢出,第一个用了获取,没出发异常,第二次写入才触发的异常(后来发现exp就触发了一次整数溢出)
漏洞利用
参考:http://bobao.360.cn/learning/detail/3029.html
下面只是分析别人的结果
先看信息泄露,贴出跟poc不同的部分,可以看到先获取marginLeftAddress,保存后,就将那个地址的值改为我们想要读取的值,比如下面的0x7ffe0300(在这个地址处存放的值与ntdll.dll模块的基地址有一个固定的偏移),之后就通过a[i].marginLeft泄露0x7ffe0300里面的值,但是不要忘记恢复marginLeftAddress的值,最后通过偏移计算出ntdll的基址
1 | for (var i=0; i<0x400; i++) { |
控制eip是下面的,
1 | vml1.dashstyle.array.length = 0 - 1; |
堆喷代码